/*
 * Copyright 2012 Andrea Parodi
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *        http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */

package eban.storebyrules.results;

/**
 * This interface provides forward only, read only, random access to
 * the result set returned by a database query.
 * Rows can be accessed one by one, and for each row returned
 * random readonly access is provided to values of columns.
 * <p>
 * Result instance are required to keep an index on the resultset
 * that point to curret row.
 * It must be initially positioned before start of results,
 * so that clients always has to call next() before reading column
 * values.
 * <p>
 * Please note that all implementation of this interface
 * are allowed to freely reuse Row instances once they get
 * out of currency, because of a call to next().
 * Implementations could even use one single instance of Row
 * object, because only one single row could be current at a time.
 * So clients are warned to not store Row instance over time,
 * because they are mutable.
 *
 * <p>
 * Result implementations are not required to be synchronized so
 * code using a Result from multiple threads should perform its
 * own synchronization when using the Cursor.
 * <p>
 * Result interface contain a close method.
 * Each implementation must use this method to release
 * it's resources.
 * Client code is responsible to call close() methode on
 * each result when it has done with it.
 */
public interface Result extends Iterable<Result.Row>{
    /**
     * This interface represent a row
     * of the results.
     * Row instances are used to
     * retrieve cell values given a Column
     * object.
     * They are an ordered set of cell values.
     */
    public interface Row {
        /**
         * retrieve a cell value for a given a Column
         * object.
         * @param column the column for which to retrieve the value.
         * @return value of cell at [this,column]
         */
        Object get(Column column);

        /**
         * The result who own ths row
         * @return
         */
        Result getResult();
    }

    /**
     * This interface represent a column
     * of the results.
     * Column instances are used to
     * retrieve cell values passing them
     * as parameters in Row.get method.
     * They are equally ordered
     * within one results. Each row in results
     * must hold an ordered set of values matching the ordered
     * set of Column for the results.
     */
    public interface Column {
        /**
         * The result who own this column
         * @return
         */
        Result getResult();

        /**
         * Retrieve the positional index
         * of this column.
         * @return the 0 based positional index
         * of this column.
         */
        int getIndex();

        /**
         * Retrieve the name
         * of this column.
         * @return the name  of this column.
         */
        String getName();
    }

    /**
     * This interface represent the ordered
     * set of Columns contained in this Result.
     */
    public interface Columns{
        /**
         * Return an array of all the columns
         * for this Result.
         * @return an array of all the columns
         * for this Result.
         */
        Column[] all();

        /**
         * Return a column of the result giving
         * its name.
         * @param name name of column to return
         * @return a Column instance
         */
        Column byName(String name);

        /**
         * Return column at a given index
         * @param index index of column to return
         * @return a Column instance
         */
        Column at(int index);

        /**
         * Return number of columns in the result
         * @return the number of columns in the result
         */
        int count();
    }

    /**
     * Make next available row the current.
     */
    void next();

    /**
     * return the Columns instance holding all the
     * columns for this Result
     * @return an instance of Columns
     */
    Columns columns();


    /**
     * Return the Row instance holding all the
     * value for current row.
     * Must return the special Row instance of
     * NO_CURRENT_ROW if the results are empty
     * or if all rows has been read.
     *
     * @return an instance of Row or Rows.NO_CURRENT_ROW if the results are empty
     * or if all rows has been read.
     */
    Row current();

    /**
     * Return true if there is no current row.
     * This could mean that the results are empty
     * or that all rows has been read.
     * <P>
     * row() method must return Rows.NO_CURRENT_ROW only
     * if this method return true, and vice-versa.
     * @return true if there is no current row available.
     */
    boolean atEnd();




    /**
     * Allow to close the results.
     * Implementation are required to release
     * all their resourced in this method.
     * <p>
     * Client code is responsible to call close() methode on
     * each result when it has done with it.
     */
    void close();
}
